import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import ticker
import matplotlib.patches as mpatches
import geopandas as gpd
from matplotlib.colors import LinearSegmentedColormap
import shapely as sh
from shapely.geometry import mapping
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px
from plotly.offline import init_notebook_mode
init_notebook_mode(connected=False)
import warnings
warnings.filterwarnings("ignore")
# Reading and melting the first data
df = pd.read_excel("data/ages_parties.xlsx")
df_first_2013 = df.loc[(df["year"]==2013) & (df["votes"]=="first")]
df_first_2013 = pd.melt(df_first_2013, id_vars=['age_group', "year", "votes"]).sort_values(['age_group'])
# Melting the second data
df_second_2013 = df.loc[(df["year"]==2013) & (df["votes"]=="second")]
df_second_2013 = pd.melt(df_second_2013, id_vars=['age_group', "year", "votes"]).sort_values(['age_group'])
# Defining palette for assign each party a color
palette_bright = sns.palettes.SEABORN_PALETTES["bright"]
palette_dark = sns.palettes.SEABORN_PALETTES["dark"]
color_to_cat = dict(CDU = palette_dark[0],
CSU = palette_dark[-1],
SPD = palette_bright[3],
GRÜNE = palette_bright[2],
OTHER = palette_bright[7],
DIE_LINKE = palette_bright[4],
FDP = palette_bright[-2],
AfD = palette_bright[-1])
sns.set_style("white")
# Customizing the first figure
fig, ax = plt.subplots(1,2, figsize=(15, 9))
sns.barplot(ax=ax[0],
y='age_group',
x='value',
hue='variable',
data=df_first_2013,
palette=color_to_cat,
ci=None)
plt.title("2013 German Federal Election ", x=-0.1, y=1.08, fontsize = 23)
ax[0].set_title("First Votes by Age Groups", x=0.23, y=1, fontsize=15)
ax[0].set_xlabel("Number of Votes", fontsize = 16)
ax[0].set_ylabel("")
ax[0].set(yticks=[])
ax[0].tick_params(labelsize=15)
ax[0].xaxis.set_major_formatter(ticker.EngFormatter())
ax[0].legend([])
fig.axes[0].invert_xaxis()
# Customizing the second figure
sns.barplot(ax=ax[1],
y='age_group',
x='value',
hue='variable',
data=df_second_2013,
palette=color_to_cat,
ci=None)
plt.suptitle("Second Votes by Age Groups", x=0.632, y=0.905, fontsize=14)
ax[1].set_xlabel("Number of Votes", fontsize = 16)
ax[1].set_ylabel("", fontsize = 16)
ax[1].tick_params(labelsize=15)
ax[1].tick_params(axis="y", pad=15)
ax[1].xaxis.set_major_formatter(ticker.EngFormatter())
ax[1].legend(title="", fontsize=10)
<matplotlib.legend.Legend at 0x1665e491280>
# Melting the first data
df_first_2017 = df.loc[(df["year"]==2017) & (df["votes"]=="first")]
df_first_2017 = pd.melt(df_first_2017, id_vars=['age_group', "year", "votes"]).sort_values(['age_group'])
# Melting the second data
df_second_2017 = df.loc[(df["year"]==2017) & (df["votes"]=="second")]
df_second_2017 = pd.melt(df_second_2017, id_vars=['age_group', "year", "votes"]).sort_values(['age_group'])
sns.set_style("white")
# Customizing the first figure
fig, ax = plt.subplots(1,2, figsize=(15, 9))
sns.barplot(ax=ax[0], y='age_group',
x='value',
hue='variable',
data=df_first_2017,
palette=color_to_cat,
ci=None)
plt.title("2017 German Federal Election ", x=-0.1, y=1.08, fontsize = 23)
ax[0].set_title("First Votes by Age Groups", x=0.23, y=1, fontsize=15)
ax[0].set_xlabel("Number of Votes", fontsize = 16)
ax[0].set_ylabel("")
ax[0].set(yticks=[])
ax[0].tick_params(labelsize=15)
ax[0].xaxis.set_major_formatter(ticker.EngFormatter())
ax[0].legend([])
fig.axes[0].invert_xaxis()
# Customizing the second figure
sns.barplot(ax=ax[1],
y='age_group',
x='value',
hue='variable',
data=df_second_2017,
palette=color_to_cat,
ci=None)
plt.suptitle("Second Votes by Age Groups", x=0.632, y=0.905, fontsize=14)
ax[1].set_xlabel("Number of Votes", fontsize = 16)
ax[1].set_ylabel("", fontsize = 16)
ax[1].tick_params(labelsize=15)
ax[1].tick_params(axis="y", pad=15)
ax[1].xaxis.set_major_formatter(ticker.EngFormatter())
ax[1].legend(title="", fontsize=10)
<matplotlib.legend.Legend at 0x1665eda6220>
# Setting the index of the dataframe
df.set_index("age_group", inplace=True)
# Building a dataset of percentage changes between 2017 and 2013 for first votes
df1 = df.loc[(df["year"]==2013) & (df["votes"]=="first")].drop(["votes", "year"], axis=1)
df2 = df.loc[(df["year"]==2017) & (df["votes"]=="first")].drop(["votes", "year"], axis=1)
pct_change = (df2 - df1) / df1 * 100
# Adding votes column
pct_change["votes"] = df["votes"][:6]
pct_change.reset_index(inplace=True)
# Melting the data
pct_change = pd.melt(pct_change, id_vars=['age_group', "votes"]).sort_values(['age_group'])
sns.set_style("white")
# Customizing the figure
fig, ax = plt.subplots(figsize=(15, 9))
sns.barplot(ax=ax,
x='age_group',
y='value',
hue='variable',
data=pct_change,
palette=color_to_cat,
ci=None)
ax.set_title("Percentage Change of First Votes Between 2017 and 2013 by Age Groups", x=0.4, y=1, fontsize=20)
ax.set_xlabel("Age Groups", fontsize = 16)
ax.set_ylabel("% Percentage Change", fontsize=16)
ax.tick_params(labelsize=15)
ax.legend(title="", fontsize=10, bbox_to_anchor=(1.01, 1))
<matplotlib.legend.Legend at 0x1665eeb88b0>
# Building a dataset of percentage changes between 2017 and 2013 for first votes
df1 = df.loc[(df["year"]==2013) & (df["votes"]=="second")].drop(["votes", "year"], axis=1)
df2 = df.loc[(df["year"]==2017) & (df["votes"]=="second")].drop(["votes", "year"], axis=1)
pct_change = (df2 - df1) / df1 * 100
# Adding votes column
pct_change["votes"] = df["votes"][:6]
pct_change.reset_index(inplace=True)
# Melting the data
pct_change = pd.melt(pct_change, id_vars=['age_group', "votes"]).sort_values(['age_group'])
sns.set_style("white")
# Customizing the figure
fig, ax = plt.subplots(figsize=(15, 9))
sns.barplot(ax=ax,
x='age_group',
y='value',
hue='variable',
data=pct_change,
palette=color_to_cat,
ci=None)
ax.set_title("Percentage Change of Second Votes Between 2017 and 2013 by Age Groups", x=0.42, y=1, fontsize=20)
ax.set_xlabel("Age Groups", fontsize = 16)
ax.set_ylabel("% Percentage Change", fontsize=16)
ax.tick_params(labelsize=15)
ax.legend(title="", fontsize=10, bbox_to_anchor=(1.01, 1))
<matplotlib.legend.Legend at 0x1665f1fd550>
# Defining the dataset
df1 = df.loc[(df["year"]==2013) & (df["votes"]=="second")].drop(["year", "votes"], axis=1).sort_values(['age_group'])
# Creating subplots, using 'domain' type for pie charts
specs = [[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}]]
# Defining the figure
fig = make_subplots(rows=2, cols=4, specs=specs)
# Defining pie charts
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["CDU"],
title="CDU",
textposition='inside',
sort=False), 1, 1)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["SPD"],
title="SPD",
textposition='inside',
sort=False), 1, 2)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["FDP"],
title="FDP",
textposition='inside',
sort=False), 1, 3)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["DIE_LINKE"],
title="DIE LINKE",
textposition='inside',
sort=False), 1, 4)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["GRÜNE"],
title="GRÜNE",
textposition='inside',
sort=False), 2, 1)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["CSU"],
title="CSU",
textposition='inside',
sort=False), 2, 2)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["AfD"],
title="AfD",
textposition='inside',
sort=False), 2, 3)
fig.add_trace(go.Pie(labels=df1.index,
name="Age Group",
values=df1["OTHER"],
title="OTHER",
textposition='inside',
sort=False), 2, 4)
# Tuning layout and hover info
fig.update_traces(hoverinfo='label+name')
fig.update_layout(width=1000, height=700,
legend=dict(orientation="h", x=0.4, y=1.05),
title=dict(text='Percentage of Age Groups by Parties ', font_size=20),
annotations=[go.layout.Annotation(showarrow=False, text='2013 Second Votes', x=-0.03, y=1.08)])
fig = go.Figure(fig)
fig.show()
# Defining the dataset
df2 = df.loc[(df["year"]==2017) & (df["votes"]=="second")].drop(["year", "votes"], axis=1).sort_values(['age_group'])
# Creating subplots, using 'domain' type for pie charts
specs = [[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}],
[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}]]
# Defining the figure
fig = make_subplots(rows=2, cols=4, specs=specs)
# Defining pie charts
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["CDU"],
title="CDU",
textposition='inside',
sort=False), 1, 1)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["SPD"],
title="SPD",
textposition='inside',
sort=False), 1, 2)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["FDP"],
title="FDP",
textposition='inside',
sort=False), 1, 3)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["DIE_LINKE"],
title="DIE LINKE",
textposition='inside',
sort=False), 1, 4)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["GRÜNE"],
title="GRÜNE",
textposition='inside',
sort=False), 2, 1)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["CSU"],
title="CSU",
textposition='inside',
sort=False), 2, 2)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["AfD"],
title="AfD",
textposition='inside',
sort=False), 2, 3)
fig.add_trace(go.Pie(labels=df2.index,
name="Age Group",
values=df2["OTHER"],
title="OTHER",
textposition='inside',
sort=False), 2, 4)
# Tuning layout and hover info
fig.update_traces(hoverinfo='label+name')
fig.update_layout(width=1000, height=700,
legend=dict(orientation="h", x=0.4, y=1.05),
title=dict(text='Percentage of Age Groups by Parties ', font_size=20),
annotations=[go.layout.Annotation(showarrow=False, text='2017 Second Votes', x=-0.03, y=1.08)])
fig = go.Figure(fig)
fig.show()
# Reading the datasets.(Turnout rates by regions and shapefile of Germany)
shp = gpd.read_file("data/regions_shapefiles/DEU_adm1.shp")
df = pd.read_excel("data/regions_turnout.xlsx")
# Changing column name to merge the datasets
shp.rename(columns={'ID_1':'land_number'}, inplace=True)
# Defining a function to convert shp to geojson format
def df_to_geojson(df, properties, geom='geometry'):
geojson = {'type':'FeatureCollection', 'features':[]}
k = 0
for _, row in df.iterrows():
features = {'type':'Feature',
'properties':{},
'geometry':{}}
features["geometry"] = mapping(row[geom])
for prop in properties:
features['properties'][prop] = row[prop]
geojson['features'].append(features)
k += 1
return geojson
# Converting the dataframe to gejson
cols = ["land_number"]
geojson = df_to_geojson(shp, cols)
# Merging two datasets
geo_df = gpd.GeoDataFrame.from_features(
geojson["features"]
).merge(df, on="land_number").set_index("land_number")
# Plotting the figure
fig = px.choropleth(geo_df,
geojson=geo_df["geometry"],
locations=geo_df.index,
hover_data={"year": False},
labels={"turnout": "% Turnout",
"year": "Year"},
hover_name="Land",
facet_col ="year",
color="turnout",
color_continuous_scale='PuBu',
projection="mercator")
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(title_text="German Federal Election: Turnout by Regions", width=1000, height=450)
fig.show()